package lock;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;

/**
 * 案例：基于自定义同步器实现生产者消费者等待队列分离的生产者-消费者模型
 */
class ProduceConsumeQueue<T> {
    private final LinkedList<T> queue = new LinkedList<>();
    private final static int MAX_COUNT = 10;//最大库存

    MyLock myLock = new MyLock();
    Condition producerWaitCond = myLock.newCondition();//生产者等待队列
    Condition consumerWaitCond = myLock.newCondition();//消费者等待队列

    public void put(T resource) {
        try {
            producerWaitCond.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myLock.lock();
        try {
            while (queue.size() == MAX_COUNT) {
                //若库存已满，则将当前线程（生产者）加入生产者等待队列阻塞等待
                System.out.println("生产者:队列已满，无法插入...");
                producerWaitCond.await();
            }
            //否则生产一个资源，并从消费者等待队列随机唤醒一个消费者线程到同步队列参与锁竞争
            queue.addFirst(resource);
            System.out.println("生产者:插入"+resource + "! ! !");
            consumerWaitCond.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            myLock.unLock();
        }
    }

    public void take() {
        myLock.lock();
        try {
            while (queue.size() == 0) {
                //若库存为空，则将当前线程（消费者）加入消费者等待队列阻塞等待
                System.out.println("消费者:队列为空，无法取出...");
                consumerWaitCond.await();
            }
            //否则消费一个资源，并从生产者者等待队列随机唤醒一个生产者线程到同步队列参与锁竞争
            queue.removeLast();
            System.out.println("消费者:取出消息! !!");
            producerWaitCond.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            myLock.unLock();
        }
    }
}


class PCQueueTest {
    public static void main(String[] args) {
        ProduceConsumeQueue<String> produceConsumeQueue = new ProduceConsumeQueue<>();
        //生产者线程 可多个
//        for (int p = 1;p <= 3;p++) {
//            new Thread(() -> {
//                for (int i = 0;i < 50;i++) {
//                    produceConsumeQueue.put("消息" + Thread.currentThread().getName() + "-msg" + i);//生产
//                }
//            }).start();
//        }
//        //消费者线程 可多个
//        for (int c = 1;c <= 3;c++) {
//            new Thread(() -> {
//                for (int i = 0; i < 50; i++) {
//                    produceConsumeQueue.take();//消费
//                }
//            }).start();
//        }
        produceConsumeQueue.put("消息" + Thread.currentThread().getName() + "-msg" + 1);//生产
    }
}